`timescale 1ns / 1ns
//--------------------------------------------------------------------------------------------------------
// Module  : lckfb_usb_audio
// Type    : synthesizable, fpga top
// Standard: Verilog 2001 (IEEE1364-2001)
// Function: Gowin USB UAC Audio Card
// Powered by JerryTech, USB and UAC powered by WangXuan95
// USB and UAC proctocol refers to: https://github.com/WangXuan95/FPGA-USB-Device
//                                  https://gitee.com/wangxuan95/FPGA-USB-Device
//--------------------------------------------------------------------------------------------------------

module lckfb_usb_audio (
    // clock
    input  wire        clk50mhz,     // connect to a 50MHz oscillator
    // reset button
    input  wire        key_vol_up,   // Volume up
    input  wire        key_vol_down, // Volume down
    // LED
    output wire        led_green,
    output wire        led_red,
    output wire        led_blue,
    //Seg display
    output wire [7 :0] seg_display,  // Common anode seg display
    // USB signals
    output wire        usb_dp_pull,  // connect to USB D+ by an 1.5k resistor
    inout              usb_dp,       // connect to USB D+
    inout              usb_dn,       // connect to USB D-

    output wire PEN,

    output wire audio_ws,
    output wire audio_bck,
    output wire audio_din,
    // debug output info, only for USB developers, can be ignored for normally use
    output wire        uart_tx       // If you want to see the debug info of USB device core, please connect this UART signal to host-PC (UART format: 115200,8,n,1), otherwise you can ignore this signal.
);


assign PEN = 1'b0;//PA set on default

//-------------------------------------------------------------------------------------------------------------------------------------
// The USB controller core needs a 60MHz clock, this PLL module is to convert clk50mhz to clk60Mhz
// The Audio driver core needs a 3.072Mhz clock, this PLL module is to convert clk50mhz to 3.072Mhz
//-------------------------------------------------------------------------------------------------------------------------------------

wire       clk60mhz;
wire       audio_clk; 
wire       usb_clk_locked;
wire       audio_clk_locked;   

clock_tree u_clock_tree(
    .fpga_clk       (clk50mhz),

    .usb_clk        (clk60mhz),
    .usb_resetn     (usb_clk_locked),

    .audio_clk      (audio_clk),
    .audio_resetn   (audio_clk_locked)

);

wire [15:0] audio_l;
wire [15:0] audio_r;
wire [31:0] audio_data;
wire [31:0] audio_data_vol;
wire        audio_en;
wire [31:0] audio_fifo_out;
wire        fifo_read_en;
wire        audio_o_en_reg;
wire        audio_fifo_rd_en;
wire        Almost_Empty;
wire        usb_rstn;
wire        fifo_full;

assign audio_data = {audio_r,audio_l};

async_fifo # (
   .DATA_WIDTH(32),
   .ADDR_LEN(32),
   .PROGRAM_FULL_SET(24),
   .PROGRAM_FULL_CLR(12),
   .PROGRAM_EMPTY_SET(2),
   .PROGRAM_EMPTY_CLR(16)
) u_audio_fifo
(
    .rd_clk(audio_clk),
    .rd_reset(~audio_clk_locked),

    .wr_clk(clk60mhz),
    .wr_reset(~ usb_clk_locked),

    .wr_en(audio_en && (~fifo_full)),
    .wr_data(audio_data),

    .rd_en(fifo_read_en),
    .rd_data(audio_fifo_out),

    .wr_full(fifo_full),
    .rd_empty(),
    .wr_full_program(),
    .rd_empty_program(Almost_Empty)   
);

volume_control u_volume_control(
    .sys_clk            ( audio_clk             ),
    .reset              ( ~audio_clk_locked     ),

    .key_vol_up         ( key_vol_up            ),
    .key_vol_down       ( key_vol_down          ),

    .audio_data_in      ( audio_fifo_out        ),
    .audio_data_out     ( audio_data_vol        ),

    .seg_display        ( seg_display           )
);

LSBJ_audio_driver u_audio_driver(
    .audio_clk          ( audio_clk             ),
    .reset              ( ~audio_clk_locked     ),
    .left_data          ( audio_data_vol[15: 0] ),
    .right_data         ( audio_data_vol[31:16] ),
    .fifo_read_ready    ( ~Almost_Empty         ),
    .fifo_read_en       ( fifo_read_en          ),
    .audio_ws           ( audio_ws              ),
    .audio_bck          ( audio_bck             ),
    .audio_din          ( audio_din             )
);

led_driver u_led_driver
(
    .sys_clk    (audio_clk),
    .reset      (~audio_clk_locked),

    .fifo_empty (Almost_Empty),
    .usb_rstn   (usb_rstn),

    .led_red    (led_red),
    .led_green  (led_green),
    .led_blue   (led_blue)
);

//-------------------------------------------------------------------------------------------------------------------------------------
// USB-UAC audio output (speaker) and input (microphone) device 
//-------------------------------------------------------------------------------------------------------------------------------------

// Here we simply make a loopback connection for testing.
// The audio output will be returned to the audio input.
// You can play music to the device, and then use a record software to record voice from the device. The music you played will be recorded.


usb_audio_top #(
    .DEBUG           ( "FALSE"             )    // If you want to see the debug info of USB device core, set this parameter to "TRUE"
) u_usb_audio (
    .rstn            ( usb_clk_locked      ),
    .clk             ( clk60mhz            ),
    // USB signals
    .usb_dp_pull     ( usb_dp_pull         ),
    .usb_dp          ( usb_dp              ),
    .usb_dn          ( usb_dn              ),
    // USB reset output
    .usb_rstn        ( usb_rstn            ),   // 1: connected , 0: disconnected (when USB cable unplug, or when system reset (rstn=0))
    // user data : audio output (host-to-device, such as a speaker), and audio input (device-to-host, such as a microphone).
    .audio_out_valid ( audio_en            ),
    .audio_lo        ( audio_l             ),   // left-channel output : 16-bit signed integer, which will be valid when audio_en=1
    .audio_ro        ( audio_r             ),   // right-channel output: 16-bit signed integer, which will be valid when audio_en=1
    // debug output info, only for USB developers, can be ignored for normally use
    .debug_en        (                     ),
    .debug_data      (                     ),
    .debug_uart_tx   ( uart_tx             )
);



endmodule
